#include "StdAfx.h"
#include "Interpreter.h"
#include <iostream>
using namespace std;

CInterpreter::CInterpreter(vector<int> &tokenStream, CBird * bird):m_tokenStream(tokenStream),m_bird(bird)
{

}

CInterpreter::~CInterpreter(void)
{
}

void CInterpreter::interpret()
{
	vector<int> expression;

	for ( int i = 0; i < m_tokenStream.size(); i++ )
	{
		if ( m_tokenStream[i] == CTokenStream::SEMICOLON )
		{
			if(!expression.empty())
				doAction(expression);
			expression.clear();
		}
		else
		{
			expression.push_back(m_tokenStream[i]);
		}
	}
	echoErrors();
}

void CInterpreter::doAction(const vector<int> & expression)
{
	if ( m_errors.size() == 0 )
	{
		if ( expression.size() == 1 )
		{
			startComand(expression[0]);
		}
		else if ( expression[0] == CTokenStream::REPETITION_WHILE )
		{ 
			startRepetition(expression);
		}
		else
		{
			m_errors.push_back(INTERPRET_ERROR);
		}
	}
}

void CInterpreter::echoErrors()
{
	for( int i = 0; i < m_errors.size(); i++ )
	{
		switch (m_errors[i])
		{
		case INTERPRET_ERROR:
			cout << "ERROR: bad expression" << endl;
			break;
		case NOT_EXISTING_COMMAND:
			cout << "ERROR: command isn't exist" << endl;
			break;
		case BAD_WHILE_SYNTAX:
			cout << "ERROR: bad while syntax" << endl;
			break;
		}
	}
}

void CInterpreter::startRepetition(const vector<int> & expression)
{	
	bool rightSyntax = ( expression[1] == CTokenStream::LEFT_PARANTHESIS &&
					     expression[2] == CTokenStream::VARIABLE &&
					     expression[4] == CTokenStream::RIGHT_PARANTHESIS &&
					     expression.size() > 5 );
	if ( rightSyntax )
	{
		vector<int> newExpression;
		for ( int i = 5; i < expression.size(); i++ )
		{
			newExpression.push_back( expression[i] );
		}
		if ( m_variablesValues.size() <= expression[3] ) //keep variable's value in memory
		{
			m_variablesValues.push_back(rand() % 2 + 1);
		}
		for ( int i = 0; i < m_variablesValues[expression[3]]; i++ )
		{
			doAction(newExpression);
		}
	}
	else
	{
		m_errors.push_back(BAD_WHILE_SYNTAX);
	}
}

void CInterpreter::startComand(int command)
{
	switch (command)
	{
	case CTokenStream::COMMAND_FLY:
		fly();
		break;
	case CTokenStream::COMMAND_QUACK:
		quack();
		break;
	case CTokenStream::COMMAND_RIGHT:
		right();
		break;
	default:
		m_errors.push_back(NOT_EXISTING_COMMAND);
	}
}

void CInterpreter::fly()
{
	m_bird->fly();
}

void CInterpreter::quack()
{
	m_bird->quack();
}

void CInterpreter::right()
{
	m_bird->right();
}
